package org.example.springgobang.game;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.example.springgobang.model.MatchResponse;
import org.example.springgobang.model.Room;
import org.example.springgobang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.server.WebSession;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

/**
 * 匹配器
 * 处理不同玩家之中的匹配
 */
@Slf4j
@Component
public class Matcher {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private RoomManager roomManager;

    //创建三个不同的队列
    private Queue<User> lowQueue=new LinkedList<User>();
    private Queue<User> normalQueue=new LinkedList<User>();
    private Queue<User> highQueue=new LinkedList<User>();

    //添加
    public void add(User user) {
        int score=user.getScore();
        if(score<2000){
            //每当有玩家进入队列之后 进行通知
            synchronized(lowQueue){
                lowQueue.offer(user);
                lowQueue.notify();
            }
            log.info("把玩家"+user.getUsername()+"添加到lowQueue之中");
        }else if(score>=2000 && score<3000){
            synchronized(normalQueue){
                normalQueue.offer(user);
                normalQueue.notify();
            }
            log.info("把玩家"+user.getUsername()+"添加到normalQueue之中");
        }else {
            synchronized(highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            log.info("把玩家"+user.getUsername()+"添加到highQueue之中");
        }
    }

    //移除
    public void remove(User user) {
        int score=user.getScore();
        if(score<2000){
            synchronized(lowQueue){
                lowQueue.remove(user);
            }
            log.info("把玩家"+user.getUsername()+"移除lowQueue");
        }else if(score>=2000 && score<3000){
            synchronized(normalQueue){
                normalQueue.remove(user);
            }
            log.info("把玩家"+user.getUsername()+"移除normalQueue");
        }else {
            synchronized(highQueue){
                highQueue.remove(user);
            }
            log.info("把玩家"+user.getUsername()+"移除highQueue");
        }
    }

    //创建三个线程 分别对三个队列进行扫描
    public Matcher(){
        Thread lowT=new Thread(()->{
           while(true){
               handlerMatch(lowQueue);
           }
        });
        lowT.start();

        Thread normalT=new Thread(()->{
            while(true){
                handlerMatch(normalQueue);
            }
        });
        normalT.start();

        Thread highT=new Thread(()->{
            while(true){
                handlerMatch(highQueue);
            }
        });
        highT.start();
    }

    private void handlerMatch(Queue<User> matcherQueue) {
        synchronized(matcherQueue){
            try {
                //1、使用 while 循环检测是否满足最低人数限度
                while (matcherQueue.size()<2){
                    //如果不这样 会出现 “忙等” 问题
                    matcherQueue.wait();
                    //wait 等待 notify
                    //其实可以用 sleep() 方法 但这不是最优解
                }
                //2、取出两个玩家进行匹配 获取到两个玩家的 WebSocket
                User player1=matcherQueue.poll();
                User player2=matcherQueue.poll();
                log.info("正在匹配玩家：["+player1.getUsername()+","+player2.getUsername()+"]");
                WebSocketSession session1 = onlineUserManager.getGameHall(player1.getUserId());
                WebSocketSession session2 = onlineUserManager.getGameHall(player2.getUserId());
                /**
                 * 3、双重保险 尽管在 OnlineUserMapper 已经进行了相关处理
                 */
                if(session1==null){
                    matcherQueue.offer(player2);
                    return;
                }
                if(session2==null){
                    matcherQueue.offer(player1);
                    return;
                }
                if(session1==session2){
                    matcherQueue.offer(player1);
                    return;
                }
                //4、把两个玩家添加到房间
                Room room=new Room();
                roomManager.add(room,player1.getUserId(),player2.getUserId());

                //5、给玩家反馈信息：匹配成功 需要分别反馈给两个玩家
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setMessage("matchSuccess");
                String json=objectMapper.writeValueAsString(response);
                session1.sendMessage(new TextMessage(json));
                session2.sendMessage(new TextMessage(json));

            }catch (InterruptedException | IOException e){
                e.printStackTrace();
            }
        }


    }
}
